#!coding:utf-8
from graphics import *
from socket import *
from time import ctime
import Queue
import threading
import re
import signal
import struct
import Image as Img
import StringIO
class Bmp():
    def __init__(self,bmp=None):
        self.bfType = 0
        self.bfSize = 0
        self.bfReserved1 = 0
        self.bfReserved2 = 0
        self.bfOffBits = 0
        self.biSize = 0
        self.biWidth = 0
        self.biHeight = 0
        self.biPlanes = 0
        self.biBitCount = 0
        self.biCompression = 0
        self.biSizeImage = 0
        self.biXPelsPerMeter = 0
        self.biYPelsPerMeter = 0
        self.biClrUsed = 0
        self.biClrImportant = 0
        self.data = ''
        if bmp is not None:
            self.unpack(bmp)
    def unpack(self,bmp):
        self.bfType = struct.unpack('2s', bmp[:2])
        self.bfSize,self.bfReserved1,self.bfReserved2,self.bfOffBits,self.biSize,self.biWidth,self.biHeight,self.biPlanes,self.biBitCount,\
        self.biCompression,self.biSizeImage,self.biXPelsPerMeter,self.biYPelsPerMeter,self.biClrUsed,self.biClrImportant = \
        struct.unpack('I2H2I2i2H2I2i2I', bmp[2:54])
        
        self.data = bmp[56:]
    def showBmpInfo(self):
        print("bfType:%s" % self.bfType)
        print("bfSize:%d" % self.bfSize)
        print("bfReserved1:%d" % self.bfReserved1)
        print("bfReserved2:%d" % self.bfReserved2)
        print("bfOffBits:%d" % self.bfOffBits)
        print("biSize:%d" % self.biSize)
        print("biWidth:%d" % self.biWidth)
        print("biHeight:%d" % self.biHeight)
        print("biPlanes:%d" % self.biPlanes)
        print("biBitCount:%d" % self.biBitCount)
        print("biCompression:%d" % self.biCompression)
        print("biSizeImage:%d" % self.biSizeImage)
        print("biXPelsPerMeter:%d" % self.biXPelsPerMeter)
        print("biYPelsPerMeter:%d" % self.biYPelsPerMeter)
        print("biClrUsed:%d" % self.biClrUsed)
        print("biClrImportant:%d" % self.biClrImportant)

class Pos(threading.Thread):
    def __init__(self, host='', port=12345, clients=10, dname='simulate', wsize=(340, 440), screenSize=(320, 240), sxOffset=10, syOffset=10):
        '''
        
        '''
        super(Pos, self).__init__(name = dname)

        self.buff_size = 1024
        self.host = host
        self.port = port
        self.max_clients = clients
        self.wsize = wsize
        self.wWidth = wsize[0]
        self.wHeight = wsize[1]
        self.screenSize = screenSize
        self.sWidth = screenSize[0]
        self.sHeight = screenSize[1]
        self.sxOffset = sxOffset
        self.syOffset = syOffset
        self.name = dname
        self.processThreadId=''
        self.rxq = Queue.Queue(maxsize = -1)
        self.odq = Queue.Queue(maxsize = -1)
        self.color = {0:'white',1:'black',2:'red',3:'green',4:'yellow'}
        #设置画布窗口名和尺寸
        self.win = GraphWin(self.name, self.wsize[0], self.wsize[1])
        #画矩形
        rect = Rectangle(Point(self.sxOffset, self.syOffset), Point(self.sxOffset + self.sWidth, self.syOffset + self.sHeight))
        rect.setOutline('white') #外围轮廓颜色
        rect.setFill('white') #填充颜色
        rect.draw(self.win)
        threading.Thread(target=self._doProcess, args=(), name='process').start()
    def __exit__(self):
        self.win.close()
        pass

    def _doProcess(self):
        while True:
            order=''
            data = self.rxq.get()
            if data != '02':
                continue
            data = self.rxq.get().decode("HEX")
            data += self.rxq.get().decode("HEX")
            data += self.rxq.get().decode("HEX")
            data += self.rxq.get().decode("HEX")
            dlen = int(data,16)
            print 'doprodata:%d %s' % (dlen, data)
            opcode = self.rxq.get().decode("HEX")
            order += opcode
            data=''
            if dlen == 0:
                continue
            dlen *= 2
            while dlen:
                data += self.rxq.get().decode("HEX")
                dlen -= 1
            self.rxq.get() #0x03
            order += data
            self.odq.put(order)

    def _getOrder(self):
        data = self.odq.get()
        return data[0]+ data[1:].decode("HEX")
    def runServer(self):
        self.start()
        while True:
            order = self._getOrder()
            opCode = order[0]
            data = re.findall(r'(.{2})',order[1:].encode("HEX"))
            # print 'opCode:%s data:%s' % (opCode, data)
            if opCode == 'L':
                x1 = int(data[0]+data[1], 16) + self.sxOffset
                y1 = int(data[2]+data[3], 16) + self.syOffset
                x2 = int(data[4]+data[5], 16) + self.sxOffset
                y2 = int(data[6]+data[7], 16) + self.syOffset
                color = int(data[8], 16)

                line = Line(Point(x1, y1), Point(x2, y2))
                line.setFill(self.color[color]) #填充颜色
                line.draw(self.win)

                print 'line x1:%d y1:%d x2:%d y2:%d color:%d' %(x1,y1,x2,y2,color)
            elif opCode == 'R':
                x1 = int(data[0]+data[1], 16) + self.sxOffset
                y1 = int(data[2]+data[3], 16) + self.syOffset
                x2 = int(data[4]+data[5], 16) + self.sxOffset
                y2 = int(data[6]+data[7], 16) + self.syOffset
                linecolor = int(data[8], 16)
                fillcolor = int(data[9], 16)

                rect = Rectangle(Point(x1, y1), Point(x2, y2))
                rect.setOutline(self.color[linecolor]) #外围轮廓颜色
                rect.setFill(self.color[fillcolor]) #填充颜色
                rect.draw(self.win)

                print 'rectanle x1:%d y1:%d x2:%d y2:%d linecolor:%d fillcolor:%d' %(x1,y1,x2,y2,linecolor,fillcolor)
            elif opCode == 'P':
                x = int(data[0]+data[1], 16) + self.sxOffset
                y = int(data[2]+data[3], 16) + self.syOffset
                color = int(data[4], 16)

                pt = Point(x, y)
                pt.setFill(self.color[color])
                pt.draw(self.win)

                print 'point x:%d y:%d color:%d' %(x,y,color)
            elif opCode == 'C':
                x = int(data[0]+data[1], 16) + self.sxOffset
                y = int(data[2]+data[3], 16) + self.syOffset
                radius = int(data[4]+data[5], 16)
                linecolor = int(data[6], 16)
                fillcolor = int(data[7], 16)

                cir = Circle(Point(x, y), radius)
                cir.setOutline(self.color[linecolor]) #外围轮廓颜色
                cir.setFill(self.color[fillcolor]) #填充颜色
                cir.draw(self.win)

                print('circle x:%d y:%d radius:%d linecolor:%d fillcolor:%d' % (x,y,radius,linecolor,fillcolor))
            elif opCode == 'B':
                x = int(data[0]+data[1], 16) + self.sxOffset
                y = int(data[2]+data[3], 16) + self.syOffset
                # print 'joindata:%s' % ''.join(data[4:])
                bmp = ''.join(data[4:]).decode("HEX")
                
                b = Bmp(bmp)
                b.showBmpInfo()

                bmpdata = bmp[b.bfOffBits:]
                # print 'bmp:' % struct.unpack('B'*len(bmp), bmp)
                # im = Img.open(StringIO.StringIO(bmp))
                # im.load()
                # im.show()
                
                for i in range(0, b.biWidth):
                    for j in range(0, b.biHeight):
                        d = struct.unpack('B',bmpdata[i*b.biWidth*2+j*2])[0]
                        if d :
                            pt = Point(x+i, y+j)
                            pt.setFill('black')
                            pt.draw(self.win)
                data = bmpdata

                #print('bitmap x:%d y:%d data:%s' % (x,y, data))
            else:
                print 'opcode err:%s' % opCode
    def run(self):

        ADDR=(self.host, self.port)
        #self.processThreadId = threading.Thread(target=self._doProcess)
        #self.processThreadId.start()

        try:
            sock=socket(AF_INET, SOCK_STREAM)

            sock.bind(ADDR)

            sock.listen(self.max_clients)
        except Exception, e:
            print(e)

        while True:
            print('waiting for connection')
            try:
                tcpClientSock, addr=sock.accept()
                print('connect from ', addr)
            except Exception,e:
                print(e)
                break
            while True:
                try:
                    data=tcpClientSock.recv(self.buff_size)
                except Exception, e:
                    print(e)
                    tcpClientSock.close()
                    break
                if not data:
                    break
                #s='Hi,you send me :[%s] %s' %(ctime(), data.decode('utf8'))
                #tcpClientSock.send(s.encode('utf8'))
                #print([ctime()], ':', data.decode('utf8'))
                print 'recv1:',data
                data = re.findall(r'(.{2})',data.encode("HEX"))
                print 'recv',data
                for d in data:
                    self.rxq.put(d)

        sock.close()

#lcd_server()
def demo():
    #设置画布窗口名和尺寸
    win = GraphWin('simulate LCD', 400, 400)

    #画点
    pt = Point(100, 100)
    pt.draw(win)

    #画圆
    cir = Circle(Point(200, 200), 75)
    cir.draw(win)
    cir.setOutline('red') #外围轮廓颜色
    cir.setFill('yellow')   #填充颜色

    #画线
    line = Line(Point(350, 100), Point(250, 100))
    line.draw(win)

    #画矩形
    rect = Rectangle(Point(300, 300), Point(400, 400))
    rect.setOutline('red') #外围轮廓颜色
    rect.setFill('blue') #填充颜色
    rect.draw(win)

    #画椭圆
    oval = Oval(Point(150, 150), Point(300, 300))
    oval.setFill('red') #填充颜色
    oval.draw(win)

    #显示文字
    message = Text(Point(win.getWidth()/2, 20), 'Click anywhere to quit.')
    message.draw(win)

    #关闭画布窗口
    win.getMouse()
    win.close()


def sigint_handler(signum, frame):  
    print('You choose to stop me.')  
    exit() 

def main():
    '''
    cmd:
        line(L) x1,y1,x2,y2,color
        rectanle(R) x1,y1,x2,y2,linecolor,fillcolor
        point(P) x,y,color
        circle(C) x,y,radius,linecolor,fillcolor
        bitmap(B) x,y,data
    '''
    # signal.signal(signal.SIGINT, sigint_handler)
    # signal.signal(signal.SIGHUP, sigint_handler)
    # signal.signal(signal.SIGTERM, sigint_handler)
    Pos().runServer()
    # s='\x02\x32'
    #time.sleep(3)
    win = GraphWin("win", 400, 400)
    img = Image(Point(0,0), './android.gif')
    img.draw(win)
    win.getMouse()
    win.close()

    print 'exit'



if __name__ == '__main__':
    main()
    pass




